<template>
    <rx-dialog @handOk="handSave" @cancel="cancel">
        <a-form :form="form" class="rx-menu-form">
            <a-form-item style="display:none">
                <a-input :value="groupId"/>
            </a-form-item>

            <div class="x-authorize-layout">
                <div class="x-authorize-layout-item" v-for="item of menuConfig">
                    <div class="x-item-title">{{ item.title }}</div>
                    <div class="x-layout-contents">
                        <div class="x-item-header">
                            <div class="x-item-search">
                                <a-input placeholder="搜索关键字" @change="menuSearch($event,item)" allowClear>
                                    <a-icon slot="prefix" type="search" />
                                </a-input>
                            </div>
                            <div class="x-item-toolbar">
                                <a-checkbox :checked="item.checkAll" @change="onChange($event,item)">
                                    {{$ti18('rxList.selectAll','全选')}}
                                </a-checkbox>
                                <a-checkbox :checked="item.checkStrictly" @change="changeCheckStrictly($event,item)">
                                    {{i18n('cascadeSelect','级联选择')}}
                                </a-checkbox>
                            </div>
                        </div>
                        <div class="x-item-content">
                            <div class="x-item-roll-box">
                                <rx-vue-tree
                                    :tree-data="item.searchData.length > 0? item.searchData : treeData[item.key]"
                                    v-model="item.checkedKeys"
                                    :show-checkbox="true"
                                    :check-strictly="item.checkStrictly"
                                    :showIcon="true"
                                    :field="'key'"
                                    @selectChange="(checked,tree,parentData)=>selectChange({checked,tree,parentData,config:item})"
                                >
                                </rx-vue-tree>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </a-form>
    </rx-dialog>
</template>

<script>
import SysMenuApi from '@/api/system/core/sysMenu'
import OsGroupMenuApi from '@/api/user/org/osGroupMenu'
import {BaseForm, Util, RxVueTree} from "@lowcode/jpaas-common-lib"
import OsInstTypeMenuApi from "@/api/user/org/osInstTypeMenu";
import { debounce, cloneDeep } from 'lodash-es'
export default {
    name: 'OsGroupMenuEdit2',
    mixins: [BaseForm],
    props: ['appId', 'privilegeId', "dimId", "containSub"],
    components: {RxVueTree},
    data() {
        return {
            groupId: null,
            //机构类型Id
            instType:'',
            menuConfig:[
                {
                    key:'front',
                    title:this.i18n('front','前端资源授权'),
                    checkAll:false,
                    checkStrictly:true,
                    checkedKeys:[],
                    searchData:[]
                },
                {
                    key:'backend',
                    title:this.i18n('backend','后端资源授权'),
                    checkAll:false,
                    checkStrictly:true,
                    checkedKeys:[],
                    searchData:[]
                }
            ],
            /*
            * 前/后端树形数据
            * */
            treeData:{
                front:[],
                backend:[]
            },
            /*
            * 全部数据的平铺展示
            * id:{}
            * */
            allData:{}
        }

    },
    computed:{
        fronts(){
            /*前端平铺数据*/
            return this.tile('front')
        },
        backends(){
            /*后端平铺数据*/
            return this.tile('backend')
        }
    },
    created() {
        this.loadPermissions();
    },
    methods: {
        i18n(name, text, key) {
            return this.$ti18(name, text, "osGroupPrivilege", key);
        },
        tile(type){
            let data = this.treeData[type];
            let arr = [];
            if(data){
                let loop = (list)=>{
                    for (let item of list){
                        if(!arr.includes(item.key)){
                            arr.push(item.key)
                        }
                        if(item.children && item.children.length > 0){
                            loop(item.children)
                        }
                    }
                }
                loop(data);
            }
            return arr;
        },
        filterTree(list,value){
            let data = list.filter(item=>{
                let isMatch = item.title.includes(value);
                if(item.children && item.children.length > 0){
                    item.children = this.filterTree(item.children,value);
                }
                return isMatch || item.children.length > 0
            })
            if(data.length > 0){
                return data
            }
            return []
        },
        menuSearch:debounce(function (e,item) {
            let { value } = e.target;
            let { treeData } = this;
            item.searchData =  this.filterTree(cloneDeep(treeData[item.key]),value);
            if(value && item.searchData.length === 0){
                this.$message.warning(this.i18n('noData','查询不到数据'))
            }
        },500),
        /*
        * 顶掉混入的js里面的loadData方法
        * */
        loadData() {},
        loadGroupMenu() {
            let self = this;
            OsGroupMenuApi.findMenuListByGroupId({groupId: this.pkId,privilegeId:this.privilegeId}).then(res => {
                let { fronts,backends, menuConfig } = self;
                // 因为antd 树插件勾选父节点会导致所有子节点选中,所以过滤所有父节点
                let data = res.data;
                if(Array.isArray(data) && data.length === 0){
                    return
                }
                let keys = data.reduce((p,n)=>{
                    let isBack = backends.includes(n)
                    let key = isBack? 'backend':'front';
                    p[key]? p[key].push(n) : p[key] = [n];
                    return p
                },{});
                for (let item of menuConfig) {
                    let selectKey = keys[item.key] ?? [];
                    let _data = item.key === 'front'? fronts : backends;
                    item.checkedKeys = [...selectKey];
                    if(selectKey.length === _data.length && selectKey.length > 0){
                        item.checkAll = true;
                    }
                }
            })
        },
        getParentNode(obj, id,filed){
            let getParent = (list, id) => {
                for (let item of list) {
                    if (item[filed] === id) {
                        return [item]
                    }
                    if (item.children) {
                        let node = getParent(item.children, id,filed);
                        if (node !== undefined) {
                            return node.concat(item)
                        }
                    }
                }
            }
            return getParent(obj, id)
        },
        selectChange({checked,tree,config}){
            //节点选中 同时选中父级节点；
            if(checked){
                let parenNode = this.getParentNode(this.treeData[config.key],tree['key'],'key');
                parenNode.forEach(item =>{
                    if(!config.checkedKeys.includes(item.key)){
                        config.checkedKeys.push(item.key);
                    }
                })
            }
        },
        loadPermissions() {
            this.instType = this.$route.params.instType;
            let parameter = {
                type: 'group',
                privilegeId:this.privilegeId
            }
            if (this.appId) {
                parameter.appId = this.appId;

            }
            //判断是否携带有机构类型参数
            let self = this ;

            if(this.instType != null){
                OsInstTypeMenuApi.findMenusListByInstTypeId(this.instType).then(res => {
                    self.setTreeData(res.data)
                })
            }else{
                SysMenuApi.selectMenus(parameter).then(res => {
                    self.setTreeData(res)
                })
            }
        },
        setTreeData(data){
            if(!data){ return }
            let treeData = this.buildTree(data, '0');
            this.treeData = treeData.reduce((p,n)=>{
                let key = n.appType === 0?'backend':'front';
                p[key] ? p[key].push(n) : p[key] = [n];
                return p
            },{})
            this.loadGroupMenu();
        },
        buildTree(list, parentId = "0") {
            let treeList = list.filter(item =>{
                this.allData[item.id] = item;
                return item.parentId === parentId
            }).map(item => {
                this.allData[item.id] = item;
                let iconConfig = {
                    F:'iconanniu',
                    I:'api',
                }
                let icon = iconConfig[item.menuType] || "bars";
                return {
                    key: item.id,
                    title: item.name,
                    parentId: item.parentId,
                    icon: icon,
                    appType:item.appType,
                    children: this.buildTree(list, item.id)
                }
            });
            return treeList.sort((app1,app2)=>{
                return app1.sn - app2.sn;
            });
        },

        onChange(e,item) {
            item.checkAll = e.target.checked;
            if (item.checkAll) {
                let data = this[item.key === 'front'?'fronts':'backends'];
                if(item.checkedKeys.length !== data.length){
                    for (let k of data){
                        if(!item.checkedKeys.includes(k)){
                            item.checkedKeys.push(k)
                        }
                    }
                }
            }else {
                item.checkedKeys = [];
            }
        },
        handSave() {
            const { allData } = this;
            let data = [];
            for (let item of this.menuConfig){
                item.checkedKeys.forEach(id=>{
                    let o = allData[id];
                    if(o){
                        data.push({
                            menuId: o.id,
                            appId: o.appId,
                            name: o.name,
                            remarks: o.remarks,
                            parentId: o.parentId,
                            privilegeId: this.privilegeId
                        });
                    }
                })
            }
            let self_ = this;
            OsGroupMenuApi.saveOsGroupMenu(data, this.pkId, this.containSub, this.dimId).then(res => {
                if (res.success) {
                    Util.closeWindow(self_, "ok");
                }
            });
        },
        changeCheckStrictly(e,item) {
            item.checkStrictly = e.target.checked;
        },

        //根据id获取菜单
        getMenuById(id, menus) {
            var menu;
            for (var i = 0; i < menus.length; i++) {
                if (menus[i].key == id) {
                    menu = menus[i];
                    break;
                } else {
                    if (menus[i].children && menus[i].children) {
                        menu = this.getMenuById(id, menus[i].children);
                        if (menu) break;
                    }
                }
            }
            return menu;
        }
    }
}
</script>

<style scoped>
.rx-menu-form{
    display: block;
    height: 100%;
    width: 100%;
}
.x-item-title{
    font-weight: 700;
    padding-bottom: 8px;
    color: rgba(0, 0, 0, 0.85);
}
.x-item-toolbar{
    padding: 6px 0;
}
.x-authorize-layout{
    height: inherit;
    width: inherit;
    display: flex;
    gap: 0 20px;
}
.x-layout-contents,
.x-authorize-layout-item{
    flex: 1;
    display: flex;
    flex-direction: column;
}
.x-layout-contents{
    border:1px solid #e8e8e8;
    border-radius: 6px;
}
.x-item-content{
    flex: 1;
    position: relative;
}
.x-item-roll-box{
    position: absolute;
    inset: 0;
    padding: 10px;
    overflow:scroll;
}

.x-item-header{
    padding: 10px 10px 0;
}
</style>
